其他
Win10 1909逆向(反向计算Windows内核内存布局及代码实现)
本文为看雪论坛优秀文章
看雪论坛作者ID:学技术打豆豆
0x0 前言
在最新的Windows版本中,内存动态并且很多在32位下的变量符号,Windbg现如今都没有了,变成了类似qword_1404687D8这样的东西,对于逆向内存的同学来说,非常不便,但是Windows为了提高效率来进行地址判断的前提下还是给我们留下了一条门缝,我们可以利用此机制反向推导出一些重要的内存布局。
0x1 演示
注1:最下面的两个地址是特意申请的两个地址,分别是非分页内存和分页内存地址,用来和上面的基址来比较。
注2:MMPFNDATABASE的基址对比正确。
注3:MiVaProcessSpace 是动态内核虚拟地址空间。
0x2 原理
Windows在内存设计之初,设计了一个内核Mark标记,从0xFFFF8000 0000 0000起一直标记了0x100个的标记,这里被微软根据特定的位算法进行了特别的划分(代码演示)。
其内核内存标记如下:
那这些数字代表什么意义?微软其实已经定了一个枚举类型来详细记录:
那通过这两个我们就可以反推出我们需要的内存布局(有些内存布局在这里无法得到,是因为有额外的处理流程,可以通过别的方法得到)。
0x3 简单代码实现
#include <ntddk.h>
#define NameSize 0x10
#define MiVaUnused 0
#define MiVaSessionSpace 1
#define MiVaProcessSpace 2
#define MiVaBootLoaded 3
#define MiVaPfnDatabase 4
#define MiVaNonPagedPool 5
#define MiVaPagedPool 6
#define MiVaSpecialPoolPaged 7
#define MiVaSystemCache 8
#define MiVaSystemPtes 9
#define MiVaHal 10
#define MiVaSessionGlobalSpace 11
#define MiVaDriverImages 12
#define MiVaSystemPtesLarge 13
#define MiVaKernelStacks 14
#define MiVaMaximumType 15
PCHAR TypeName[NameSize] =
{
"MiVaUnused",
"MiVaSessionSpace",
"MiVaProcessSpace",
"MiVaBootLoaded",
"MiVaPfnDatabase",
"MiVaNonPagedPool",
"MiVaPagedPool",
"MiVaSpecialPoolPaged",
"MiVaSystemCache",
"MiVaSystemPtes",
"MiVaHal",
"MiVaSessionGlobalSpace",
"MiVaDriverImages",
"MiVaSystemPtesLarge",
"MiVaKernelStacks",
"MiVaMaximumType"
};
PVOID FindBase();
PVOID FindSystemKernenlRegion(PVOID pMark);
PVOID FindBaseRegion(PVOID pMark, UCHAR Type);
VOID Unload(PDRIVER_OBJECT pDriverObject)
{
KdPrint(("end\n"));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
KdPrint(("start\n"));
pDriverObject->DriverUnload = Unload;
//第一步找到Mark地址
PVOID pMarkAddr = FindBase();
//第二步开始解析
FindSystemKernenlRegion(pMarkAddr);
PVOID NonPool = ExAllocatePoolWithTag(NonPagedPool, 0x1000, 'NonP');
PVOID Pool = ExAllocatePoolWithTag(PagedPool, 0x1000, 'ionP');
KdPrint(("NonPagePool=%llx", NonPool));
KdPrint(("PagePool=%llx", Pool));
ExFreePool(NonPool);
ExFreePool(Pool);
return STATUS_SUCCESS;
}
PVOID FindBase()
{
UNICODE_STRING FuncName;
RtlInitUnicodeString(&FuncName, L"ExAcquirePushLockExclusiveEx");
PVOID FuncAddr=MmGetSystemRoutineAddress(&FuncName);
PUCHAR var = (PUCHAR)FuncAddr;
for (int i = 0; i < 0x100; i++)
{
if (*var == 0x48 && *(var+3)==0x27)
{
return var+(*(PUINT32)(var - 4));
}
var++;
}
return 0;
}
PVOID FindSystemKernenlRegion(PVOID pMark)
{
PVOID Region = 0;
for (int i = 0; i < 0x10; i++)
{
KdPrint(("%s=%llx\n", TypeName[i], FindBaseRegion(pMark, i)));
}
}
PVOID FindBaseRegion(PVOID pMark,UCHAR Type)
{
PUCHAR var = pMark;
UINT64 pBaseAddr = 0x100;
//
for (int i = 0; i < 0x100; i++)
{
if (*(var) == Type)
{
pBaseAddr =((pBaseAddr | i) << 0x27 | 0xFFFF000000000000);
return pBaseAddr;
}
var++;
}
return 0;
}
0x4 总结
可以利用点很多,希望能让大家了解一些Windows的内存机制,以后共同学习。
看雪ID:学技术打豆豆
https://bbs.pediy.com/user-814951.htm
*本文由看雪论坛 学技术打豆豆 原创,转载请注明来自看雪社区。
推荐文章++++
* 一种枚举系统热键的思路及代码实现(Win7&Win10)
好书推荐